<template>
  <div class="user-container">
    <!-- 头部 -->
    <el-header class="user-header">用户管理</el-header>
    <!-- 卡片 -->
    <el-card class="user-card">
      <!-- 顶部 -->
      <div class="top">
        <el-button
          type="primary"
          size="mini"
          class="add-btn"
          @click="addOrEditHandler('add')"
        >
          新建
        </el-button>
        <el-input
          placeholder="按关键字搜索敲回车"
          size="mini"
          v-model="keyword"
          class="search-input"
          @keyup.enter.native="searchHandler"
        ></el-input>
        <el-button
          type="danger"
          size="mini"
          class="repeal-btn"
          @click="repealHandler"
        >
          撤销
        </el-button>
      </div>
      <!-- 表格 -->
      <el-table
        :data="userList"
        style="width: 100%"
        border
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="60" align="center">
        </el-table-column>
        <el-table-column prop="name" label="姓名" width="120" align="center">
        </el-table-column>
        <el-table-column prop="age" label="年龄" width="120" align="center">
        </el-table-column>
        <el-table-column prop="sex" label="性别" width="120" align="center">
        </el-table-column>
        <el-table-column
          prop="phone"
          label="联系电话"
          width="200"
          align="center"
        >
        </el-table-column>
        <el-table-column prop="address" label="详细地址" align="center">
        </el-table-column>
        <el-table-column label="操作" width="200" align="center">
          <template slot-scope="{ row }">
            <el-button
              type="primary"
              size="mini"
              @click="addOrEditHandler('edit', row.id)"
            >
              编辑
            </el-button>
            <el-button type="danger" size="mini" @click="deleteHandler(row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-button type="danger" size="mini" @click="batchDeleteHandler">
        批量删除
      </el-button>
    </el-card>
    <!-- 模态框 -->
    <el-dialog
      title="新建/编辑用户"
      :visible.sync="dialogVisible"
      width="40%"
      :before-close="dialogBeforeClose"
    >
      <el-form
        inline
        label-position="top"
        ref="form"
        :model="user"
        :rules="rules"
        size="mini"
      >
        <div>
          <el-form-item label="姓名" class="name" prop="name">
            <el-input v-model="user.name"></el-input>
          </el-form-item>
          <el-form-item label="性别" class="sex" prop="sex">
            <el-select v-model="user.sex" placeholder="请选择性别">
              <el-option
                v-for="(item, index) in sexList"
                :key="index"
                :label="item"
                :value="item"
              ></el-option>
            </el-select>
          </el-form-item>
        </div>
        <div>
          <el-form-item label="联系电话" prop="phone">
            <el-input v-model="user.phone"></el-input>
          </el-form-item>
        </div>
        <div>
          <el-form-item label="详细地址" prop="city">
            <el-cascader :options="options" v-model="user.city"></el-cascader>
          </el-form-item>
          <el-form-item style="margin-top: 36px" prop="detailAddress">
            <el-input
              placeholder="请输入详细地址"
              v-model="user.detailAddress"
            ></el-input>
          </el-form-item>
        </div>
      </el-form>
      <div slot="footer">
        <el-button @click="dialogBeforeClose" size="mini">取 消</el-button>
        <el-button type="primary" @click="confirmHandler" size="mini">
          确 定
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { setLocalStorage, getLocalStorage } from '../utils/storage'
export default {
  name: 'user',
  data() {
    // 电话校验
    const validatePhone = (rule, value, callback) => {
      if (!value) return callback(new Error('请填写电话字段'))
      const reg = /^1[0-9]{10}$/
      if (!reg.test(value))
        return callback(new Error('电话格式需以1开头的11位数字'))
      callback()
    }
    return {
      keyword: '', // 搜索关键字
      // 用户列表
      userList: [
        {
          id: 1,
          name: 'lxins',
          age: 22,
          sex: '男',
          phone: '13419128033',
          address: '广东省广州市天河区中山路123号',
        },
        {
          id: 2,
          name: 'curry',
          age: 35,
          sex: '男',
          phone: '13412978912',
          address: '广东省广州市番禺区中山路456号',
        },
        {
          id: 3,
          name: 'stephen',
          age: 40,
          sex: '男',
          phone: '13412977145',
          address: '广东省广州市花都区中山路456号',
        },
      ],
      historys: [], // 历史记录
      checkedUserList: [], // 选中的用户列表
      dialogVisible: false, // 模态框的状态
      // 用户表单对象
      user: {
        name: '',
        sex: '',
        phone: '',
        city: '',
        detailAddress: '',
      },
      // 表单验证规则
      rules: {
        name: [{ required: true, trigger: 'blur', message: '请填写姓名字段' }],
        sex: [{ required: true, trigger: 'change', message: '请选择性别字段' }],
        city: [
          { required: true, trigger: 'change', message: '请选择城市字段' },
        ],
        detailAddress: [
          { required: true, trigger: 'blur', message: '请填写详细地址字段' },
        ],
        phone: [{ validator: validatePhone, trigger: 'change' }],
      },
      sexList: ['男', '女'],
      // 级联选择器配置项
      options: [
        {
          label: '广东省',
          value: '广东省',
          children: [
            {
              label: '广州市',
              value: '广州市',
              children: [
                { label: '天河区', value: '天河区' },
                { label: '番禺区', value: '番禺区' },
                { label: '越秀区', value: '越秀区' },
                { label: '花都区', value: '花都区' },
                { label: '海珠区', value: '海珠区' },
              ],
            },
          ],
        },
      ],
      type: '', // 表单操作类型
      oldUser: {}, // 编辑前的用户信息
    }
  },
  methods: {
    // 数据持久化
    lastingValue() {
      !getLocalStorage('userList') && setLocalStorage('userList', this.userList)
      this.userList = getLocalStorage('userList')
      !getLocalStorage('historys') && setLocalStorage('historys', this.historys)
      this.historys = getLocalStorage('historys')
    },
    // 删除用户
    deleteHandler(user) {
      this.$msgBox
        .confirm('此操作将永久删除该用户, 是否继续?', '提示', {
          confirmButtonText: '确定删除',
          cancelButtonText: '我再想想',
          type: 'warning',
        })
        .then(() => {
          // 删除用户
          const index = this.userList.findIndex(item => item.id === user.id)
          this.userList.splice(index, 1)
          setLocalStorage('userList', this.userList)
          this.$message.success('删除成功')
          // 记录历史
          this.historys.push({ type: 'delete', data: user, index })
          setLocalStorage('historys', this.historys)
        })
        .catch(() => this.$message.info('已取消删除'))
    },
    // 批量删除
    batchDeleteHandler() {
      const { historys, userList } = this
      let { checkedUserList } = this
      if (!checkedUserList.length) return this.$message.info('至少选中一个用户')
      // 记录历史
      checkedUserList = checkedUserList.map(item => ({
        ...item,
        index: userList.findIndex(i => i.id === item.id),
      }))
      historys.push({ type: 'batchDelete', data: checkedUserList })
      setLocalStorage('historys', historys)
      // 删除
      checkedUserList.forEach(item => {
        const index = userList.findIndex(i => item.id === i.id)
        userList.splice(index, 1)
      })
      setLocalStorage('userList', userList)
      this.$message.success('批量删除成功')
    },
    // 撤销操作
    repealHandler() {
      if (!this.historys.length) return this.$message.info('无可撤销的记录')
      let tips = ''
      // 获取最后一步操作
      const history = this.historys[this.historys.length - 1]
      // 判断操作
      switch (history.type) {
        // 撤销删除
        case 'delete':
          this.userList.splice(history.index, 0, history.data)
          tips = '删除'
          break
        case 'batchDelete':
          history.data.forEach(item =>
            this.userList.splice(item.index, 0, item)
          )
          tips = '批量删除'
          break
        case 'add':
          this.userList.splice(history.index - 1, 1)
          tips = '添加'
          break
        case 'edit':
          this.userList.splice(history.index, 1, history.data)
          tips = '编辑'
          break
      }
      this.$message.success(`撤销成功，上一步操作：${tips}`)
      // 弹栈操作并持久化
      this.historys.splice(this.historys.length - 1, 1)
      setLocalStorage('userList', this.userList)
      setLocalStorage('historys', this.historys)
    },
    // 选择用户的回调
    handleSelectionChange(value) {
      this.checkedUserList = value
    },
    // 搜索用户
    searchHandler() {
      this.keyword = this.keyword.trim()
      if (!this.keyword.length)
        return (this.userList = getLocalStorage('userList'))
      this.userList = this.userList.filter(item =>
        item.name.includes(this.keyword)
      )
    },
    // 清空用户表单数据
    clearUserForm() {
      this.user = {}
      this.type = ''
      this.$nextTick(() => {
        this.$refs.form.clearValidate()
      })
    },
    // 模态框关闭回调
    dialogBeforeClose(done) {
      typeof done === 'function' ? done() : (this.dialogVisible = false)
      this.clearUserForm()
    },
    // 添加或新建用户的回调
    addOrEditHandler(type, id) {
      this.dialogVisible = true
      this.type = type
      if (type === 'edit') {
        const user = this.userList.find(item => item.id === id)
        this.oldUser = user
        // 处理地址
        user.city = []
        const cityStr = user.address.substring(0, 9)
        let count = 0
        for (let i = 1; i <= cityStr.length; i++) {
          if (i % 3 === 0) {
            user.city.push(cityStr.substring(count * 3, i))
            count++
          }
        }
        user.detailAddress = user.address.substring(9, user.address.length)
        this.user = JSON.parse(JSON.stringify(user))
      }
    },
    // 确定添加或编辑的回调
    confirmHandler() {
      this.$refs.form.validate(v => {
        if (!v) return
        // 处理地址
        const { user } = this
        user.address = user.city.join('') + user.detailAddress
        user.age = '未知'
        if (this.type === 'add') {
          // 添加操作
          this.historys.push({
            type: 'add',
            data: user,
            index: this.userList.push(user),
          })
        } else {
          // 编辑操作
          const index = this.userList.findIndex(
            item => item.id === this.user.id
          )
          this.userList.splice(index, 1, this.user)
          this.historys.push({
            type: 'edit',
            data: this.oldUser,
            index: this.userList.findIndex(item => item.id === this.oldUser.id),
          })
        }
        setLocalStorage('userList', this.userList)
        setLocalStorage('historys', this.historys)
        this.dialogVisible = false
        this.clearUserForm()
        this.$message.success(`${this.type === 'add' ? '添加' : '编辑'}成功`)
      })
    },
  },
  watch: {
    // 监听搜索关键字
    keyword(newVal) {
      !newVal.length && (this.userList = getLocalStorage('userList'))
    },
  },
  mounted() {
    this.lastingValue()
  },
}
</script>

<style lang="scss">
.user-container {
  .user-header {
    text-align: center;
    line-height: 50px;
    background-color: #fafafa;
    font-size: 18px;
  }
  .user-card {
    width: 80%;
    margin: 0 auto;
    .search-input {
      width: 300px;
      margin-left: 20px;
    }
    .repeal-btn {
      float: right;
    }

    .el-table {
      margin: 20px 0;
    }
  }
  .el-dialog__header {
    text-align: center;
  }
  .el-dialog {
    padding: 0 20px;
  }
  .el-form {
    overflow: hidden;
    .el-form-item {
      width: 230px;
    }
    .name {
      float: left;
    }
    .sex {
      float: right;
    }
  }
}
</style>
